// $Id: Plugin.cs 64 2008-05-06 18:29:47Z nvivo $

using System;
using System.ComponentModel;
using System.Configuration;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using DBLGen.Configuration;

namespace DBLGen
{
    public abstract class Plugin
    {
        #region Plugin Implementation

        protected event EventHandler SettingsChanged;

        private PluginInfo _info;
        private PluginSettings _settings;

        public PluginInfo Info
        {
            get
            {
                if (_info == null)
                    _info = new PluginInfo(this.GetType());

                return _info;
            }
        }

        public PluginSettings Settings
        {
            get
            {
                return _settings;
            }
            set
            {
                _settings = value;

                if (SettingsChanged != null)
                    SettingsChanged(this, EventArgs.Empty);
            }
        }

        #endregion

        #region Plugin Discovery and Listing

        private static List<PluginInfo> _plugins;

        private static List<PluginInfo> Plugins
        {
            get
            {
                if (_plugins == null)
                    _plugins = new List<PluginInfo>();

                return _plugins;
            }
        }

        /// <summary>
        /// Gets an array of <see cref='PluginInfo' /> for all plugins of type <see cref='ImportPlugin' /> found.
        /// </summary>
        public static PluginInfo[] GetImportPlugins()
        {
            return GetPluginsInternal(typeof(ImportPlugin));
        }

        /// <summary>
        /// Gets an array of <see cref='PluginInfo' /> for all plugins of type <see cref='ExportPlugin' /> found.
        /// </summary>
        public static PluginInfo[] GetExportPlugins()
        {
            return GetPluginsInternal(typeof(ExportPlugin));
        }

        /// <summary>
        /// Gets an array of <see cref='PluginInfo' /> for all plugins of type <see cref='BatchPlugin' /> found.
        /// </summary>
        public static PluginInfo[] GetBatchPlugins()
        {
            return GetPluginsInternal(typeof(BatchPlugin));
        }

        private static PluginInfo[] GetPluginsInternal(Type baseType)
        {
            List<PluginInfo> pluginInfoList = new List<PluginInfo>();

            foreach (PluginInfo info in _plugins)
                if (info.BaseType == baseType)
                    pluginInfoList.Add(info);

            PluginInfo[] plugins = pluginInfoList.ToArray();
            Array.Sort<PluginInfo>(plugins, PluginInfoCompare);

            return plugins;
        }

        private static int PluginInfoCompare(PluginInfo a, PluginInfo b)
        {
            return String.Compare(a.Name, b.Name, true);
        }

        #endregion

        #region Plugin Loading

        /// <summary>
        /// Activate a plugin by its <see cref="Type.FullName">FullName</see> or <see cref="Type.AssemblyQualifiedName">AssemblyQualifiedName</see>
        /// </summary>
        /// <param name="typeName">The name of the type to load.</param>
        /// <returns>An instance of the plugin.</returns>
        public static Plugin Activate(string typeName)
        {
            try
            {
                Type t = Type.GetType(typeName);

                if (t.IsSubclassOf(typeof(Plugin)))
                    return (Plugin) Activator.CreateInstance(t);
            }
            catch { }

            return null;
        }

        public static void LoadFromConfig()
        {
            Configuration.DBLGenSection dblGenSection = Configuration.DBLGenSection.Load();

            if (dblGenSection != null)
            {
                foreach (PluginElement pe in dblGenSection.Plugins)
                {
                    Type t = Type.GetType(pe.Type);
                    PluginInfo pi = new PluginInfo(t);
                    Plugins.Add(pi);
                }
            }
        }

        #endregion
    }
}
